using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using MyAlbum.Services;
using MyAlbum.Logging;
using System.IO;
using System.Web.Security;
using System.Web.UI;
using MyAlbum.Model;
using System.Net.Mail;

namespace PersonalAlbum.Controllers
{
    [OutputCache(Location = OutputCacheLocation.None)]
    [ValidateInput(false)]
    public class AdminController : ApplicationController
    {
        private readonly string HomePagePath = "~/app_data/about.html";
        private IConfiguration _config;

        public AdminController() : this(ObjectFactory.GetInstance<IConfiguration>()) { }
        public AdminController(IConfiguration config)
        {
            this._config = config;
        }
        //
        // GET: /Admin/
        [Authorize(Roles = RolesManager.AdminRoles)]
        public ActionResult Index()
        {
            return View(ViewData.Model);
        }

        [Authorize(Roles = RolesManager.AdminRoles)]
        public ActionResult Email(string host, string username, string password, int port, string email)
        {
            SmtpClient client = new SmtpClient(host);
            if (!string.IsNullOrEmpty(username) &&
                !string.IsNullOrEmpty(password))
            {
                client.Credentials = new System.Net.NetworkCredential(username, password);
            }
            client.Port = port == 0 ? 25 : port;
            TextResult result;
            try
            {
                client.Send(email, email, "test email", "mail body");
                result = new TextResult("sent");
            }
            catch (Exception e1)
            {
                result = new TextResult("Error:" + e1.Message + (e1.InnerException == null ? e1.StackTrace : e1.Message + " " + e1.InnerException.StackTrace));
            }
            return result;
        }

        [Authorize(Roles = RolesManager.AdminRoles)]
        public ViewResult Config()
        {
            WebLogger.Trace("config index");
            return View(ViewData.Model);
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult HomePageEdit()
        {
            if (!System.IO.File.Exists(Server.MapPath(HomePagePath)))
            {
                System.IO.File.Create(Server.MapPath(HomePagePath));
            }
            else
            {
                ViewData["Content"] = System.IO.File.ReadAllText(Server.MapPath(HomePagePath));
            }
            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        // [ValidateAn tiForgeryToken()]
        public ActionResult HomePageEdit(string content)
        {
            try
            {
                System.IO.File.Delete(Server.MapPath(HomePagePath));
                System.IO.File.WriteAllText(Server.MapPath(HomePagePath), content);
                return RedirectToAction("HomePageEdit");
            }
            catch (Exception e1)
            {
                var model = ViewData.Model as PersonalAlbumModel;
                WebLogger.LogError(e1, "error writing to 'about.html' file");
                if (e1.Message.IndexOf("Access to the path") > -1)
                {
                    model.ErrorMessage = "error writing to 'about.html' file, make sure you have read/write permissions and that the file is not marked as 'Read Only'";
                }
                else
                {
                    model.ErrorMessage = "error writing to 'about.html' file";
                }
                return View();
            }
        }

        [Authorize(Roles = RolesManager.AdminRoles)]
        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Entrances(string sort, int? pageNum)
        {
            WebLogger.Trace("entrance index");
            var entranceService = ObjectFactory.GetInstance<IDataService<Entrance>>();
            var model = ViewData.Model as PersonalAlbumModel;
            model.Entrances = entranceService.GetItems().OrderBy(s => s.Timestamp).Reverse();
            return View(model);
        }


        [Authorize(Roles = RolesManager.AdminRoles)]
        public ActionResult DeleteEntrance(string entranceId)
        {
            var model = (PersonalAlbumModel)ViewData.Model;
            WebLogger.Trace("delete entrance " + entranceId);
            var entranceService = ObjectFactory.GetInstance<IDataService<Entrance>>();

            try
            {
                Entrance e = entranceService.GetItemById(entranceId);
                if (e != null)
                {
                    entranceService.DeleteItem(e);
                    WebLogger.Trace("entrance deleted");
                }
                else
                {
                    WebLogger.Warning("Entrance " + entranceId + " not found for deleting");
                }
                return RedirectToAction("Entrances");

            }
            catch (Exception e1)
            {
                WebLogger.LogError(e1, "error deleting entrance");
                model.ErrorMessage = model.Localize("Global.Error");
                return View("Entrances", entranceService.GetItems().OrderBy(s => s.Timestamp).Reverse());
            }

        }

        [Authorize(Roles = RolesManager.AdminRoles)]
        // [ValidateAn tiForgeryToken()]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult UpdateConfig()
        {

            WebLogger.Trace("update config");

            try
            {
                this._config.UpdateItems(Request.Form);
                if (!string.IsNullOrEmpty(Request.Form["returnUrl"]))
                {
                    return Redirect(Request.Form["returnUrl"]);
                }
                else
                {
                    return RedirectToAction("Config");
                }

            }
            catch (Exception e1)
            {
                var model = (PersonalAlbumModel)ViewData.Model;
                WebLogger.LogError(e1, "error updating config");
                if (e1 is UnauthorizedAccessException)
                {
                    model.ErrorMessage = model.Localize("Global.Error") + " Please make sure that you have write permissions to the file \"SiteConfig.xml\" and that the file is not read only";
                }
                else
                {
                    model.ErrorMessage = model.Localize("Global.Error");
                }
                return View("Config", model);
            }

        }

        [Authorize(Roles = RolesManager.AdminRoles)]
        public ViewResult Logs()
        {
            Dictionary<string, string> files = Utils.LoadFilesFromDirectory(Server.MapPath("~/App_Data/Logs"));
            return View(files);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        [Authorize(Roles = RolesManager.AdminRoles)]
        // [ValidateAn tiForgeryToken()]
        public ActionResult DeleteFile(string fileName)
        {
            var model = (PersonalAlbumModel)ViewData.Model;
            try
            {
                if (fileName == ILogger.TraceFileName ||
                    fileName == ILogger.ErrorsFileName ||
                    fileName == WebLogger.LoggingErrors)
                {
                    Utils.DeleteErrorsFile(Path.Combine(Server.MapPath("~/App_Data/Logs"), fileName));
                    WebLogger.Trace("file " + fileName + " deleted");

                }
                else
                {
                    WebLogger.Warning("Attempt to delete invalid file : " + fileName);
                }
                return RedirectToAction("Logs");
            }
            catch (Exception e1)
            {
                WebLogger.LogError(e1, "deleting file : " + fileName);
                model.ErrorMessage = e1.Message;
                return View("Logs", Utils.LoadFilesFromDirectory(Server.MapPath("~/App_Data/Logs")));
            }
        }

        [Authorize(Roles = RolesManager.AdminRoles)]
        public ActionResult Users()
        {
            WebLogger.Trace("account users");
            var users = LoadUsers();
            ((PersonalAlbumModel)ViewData.Model).Users = users;
            return View(ViewData.Model);
        }

        private List<IUser> LoadUsers()
        {
            var users = new List<IUser>();
            foreach (MembershipUser item in Membership.GetAllUsers())
            {
                users.Add(new GenericUser(item.UserName, new List<string>(Roles.GetRolesForUser(item.UserName)).ToArray())
                {
                    Email = item.Email,
                    Password = item.GetPassword()
                });
            }
            var list = new List<SelectListItem>();
            foreach (var item in Roles.GetAllRoles())
            {
                list.Add(new SelectListItem()
                {
                    Text = item,
                    Value = item
                });
            }
            ViewData["Roles"] = list;
            return users;
        }

        [AcceptVerbs(HttpVerbs.Post)]
        // [ValidateAn tiForgeryToken()]
        [Authorize(Roles = RolesManager.AdminRoles)]
        public ActionResult DeleteUser(string name)
        {
            var model = (PersonalAlbumModel)ViewData.Model;
            try
            {
                WebLogger.Trace("delete user");
                if (Membership.DeleteUser(name))
                {
                    WebLogger.Trace("user deleted");
                    return RedirectToAction("Users");
                }
                else
                {
                    WebLogger.Trace("user not deleted");
                    model.ErrorMessage = model.Localize("Global.Error");
                    model.Users = LoadUsers();
                    return View("Users", model);
                }
            }
            catch (Exception e1)
            {
                if (e1.Message.Contains("Access to the path"))
                {
                    model.ErrorMessage = model.Localize("Global.Error") + " Please make sure that you have write permissions to the file \"SiteConfig.xml\" and that the file is not read only";

                }
                else
                {
                    model.ErrorMessage = model.Localize("Global.Error");
                }
                WebLogger.LogError(e1, "deleting user " + name);
                model.Users = LoadUsers();
                return View("Users", model);
            }
        }

        [AcceptVerbs(HttpVerbs.Post)]
        // [ValidateAn tiForgeryToken()]
        [Authorize(Roles = RolesManager.AdminRoles)]
        public ActionResult EditUser(GenericUser user, bool createNew)
        {
            var model = (PersonalAlbumModel)ViewData.Model;
            try
            {
                WebLogger.Trace("edit user");
                var oldUser = LoadUsers().FirstOrDefault(u => u.Name == user.Name);
                if (oldUser != null)
                {
                    if (createNew)
                    {
                        model.ErrorMessage = model.Localize("Account.UserNameExists");
                        return View("Users", LoadUsers());
                    }
                    var membershipUser = Membership.GetUser(user.Name);
                    if (membershipUser != null)
                    {
                        if (user.Roles.Count != oldUser.Roles.Count ||
                            user.Roles.Union(oldUser.Roles).Count() != oldUser.Roles.Count)
                        {
                            //roles  changed
                            if (oldUser.Roles.Count != 0)
                            {
                                Roles.RemoveUserFromRoles(user.Name, oldUser.Roles.ToArray());
                            }
                            if (user.Roles.Count != 0)
                            {
                                Roles.AddUserToRoles(user.Name, user.Roles.ToArray());
                            }
                        }
                        if (user.Email != oldUser.Email)
                        {
                            //email  changed
                            membershipUser.Email = user.Email ?? string.Empty;
                            Membership.UpdateUser(membershipUser);
                        }
                        if (user.Password != null &&
                            user.Password.Trim().Length > 0
                            && oldUser.Password != user.Password)
                        {
                            //we have new password and it has been changed
                            membershipUser.ChangePassword(oldUser.Password, user.Password);
                        }
                        WebLogger.Trace("user updated");
                        return RedirectToAction("Users");
                    }
                }
                else if (createNew)
                {
                    Membership.CreateUser(user.Name, user.Password, user.Email);
                    Roles.AddUserToRoles(user.Name, user.Roles.ToArray());

                    WebLogger.Trace("user created");
                    return RedirectToAction("Users");

                }
                else
                {

                }
                WebLogger.Warning("user " + user + " not found for edit");
                model.ErrorMessage = model.Localize("Global.Error");
                model.Users = LoadUsers();
                return View("Users", model);
            }
            catch (Exception e1)
            {
                model.ErrorMessage = model.Localize("Global.Error");
                WebLogger.LogError(e1, "deleting user " + user);
                model.Users = LoadUsers();
                return View("Users", model);
            }
        }

        [AcceptVerbs(HttpVerbs.Get)]
        [Authorize(Roles = RolesManager.AdminRoles)]
        public ActionResult Extensions()
        {
            return View();
        }

    }
}
